import os
import logging
import mimetypes
import traceback  # 添加traceback模块导入
from urllib.parse import quote, unquote
from flask import send_from_directory, abort

# 配置日志
logger = logging.getLogger(__name__)

class URLUtils:
    def __init__(self, dataset_path, upload_folder=None):
        self.dataset_path = dataset_path
        self.upload_folder = upload_folder
        
    def serve_dataset_file(self, encoded_filename):
        """提供数据集图片访问服务
        Args:
            encoded_filename: URL编码的文件路径
        Returns:
            Response: Flask响应对象
        """
        try:
            # URL解码文件名
            decoded_filename = unquote(encoded_filename)
            logger.info(f"解码后的文件名: {decoded_filename}")
            
            # 构建完整的文件路径
            file_path = os.path.join(self.dataset_path, decoded_filename)
            file_path = os.path.normpath(file_path)  # 规范化路径
            logger.info(f"完整文件路径: {file_path}")
            
            # 安全检查：确保访问路径在dataset_path目录下
            if not os.path.abspath(file_path).startswith(os.path.abspath(self.dataset_path)):
                logger.error(f"尝试访问非法路径: {file_path}")
                abort(403)  # Forbidden
            
            # 检查文件是否存在
            if not os.path.exists(file_path):
                logger.error(f"文件不存在: {file_path}")
                abort(404)
                
            try:
                # 获取文件类型
                mime_type, _ = mimetypes.guess_type(file_path)
                logger.info(f"文件类型: {mime_type}")
                
                # 获取文件所在的目录和文件名
                directory = os.path.dirname(file_path)
                base_filename = os.path.basename(file_path)
                
                return send_from_directory(directory, base_filename)
            except Exception as e:
                logger.error(f"创建响应失败: {str(e)}")
                abort(404)
                
        except Exception as e:
            logger.error(f"访问数据集图片出错: {str(e)}")
            abort(404)

    def serve_uploaded_file(self, filename):
        """处理上传文件的访问"""
        if not filename or not self.upload_folder:
            abort(404)
        try:
            return send_from_directory(self.upload_folder, filename)
        except Exception as e:
            logger.error(f"获取上传文件失败 {filename}: {str(e)}")
            abort(404)

    def get_relative_path(self, full_path):
        """获取相对于数据集根目录的路径"""
        try:
            return os.path.relpath(full_path, self.dataset_path)
        except Exception as e:
            logger.error(f"获取相对路径失败: {str(e)}")
            return None

    def build_dataset_url(self, image_path):
        """构建数据集图片的URL
        Args:
            image_path: 图片的完整路径
        Returns:
            str: 图片的URL路径
        """
        try:
            # 获取相对路径
            relative_path = self.get_relative_path(image_path)
            if not relative_path:
                return None
            
            # 将Windows路径分隔符转换为URL路径分隔符
            relative_path = relative_path.replace('\\', '/')
            
            # URL编码路径
            url_path = quote(relative_path)
            
            # 返回URL路径
            return f'/dataset/{url_path}'
        except Exception as e:
            logger.error(f"构建数据集URL失败: {str(e)}")
            return None

    def process_similar_images(self, similar_images):
        """处理相似图片列表，转换路径为URL"""
        processed_results = []
        
        for image in similar_images:
            try:
                if 'path' not in image:
                    logger.error(f"相似图片缺少路径信息: {image}")
                    continue
                
                # 获取图片路径并统一路径格式
                image_path = os.path.normpath(image['path'])
                
                # 检查文件是否存在
                if not os.path.isfile(image_path):
                    logger.error(f"相似图片路径不存在: {image_path}")
                    continue
                    
                # 构建相对路径
                try:
                    # 获取相对路径
                    relative_path = os.path.relpath(image_path, self.dataset_path)
                    logger.info(f"相对路径: {relative_path}")
                    
                    # 统一为正斜杠格式
                    relative_path = relative_path.replace('\\', '/')
                    url_path = quote(relative_path)
                    
                    # 创建结果项
                    url = f'/dataset/{url_path}'
                    logger.info(f"构建的URL: {url}")
                    
                    result_item = {
                        'path': url,
                        'image_url': url,  # 添加image_url属性以匹配前端期望
                        'similarity': image.get('similarity', 0),
                        'main_class': image.get('main_class', '未知'),
                        'detailed_class': image.get('detailed_class', '未知'),
                    }
                    processed_results.append(result_item)
                except Exception as e:
                    logger.error(f"处理相对路径失败 {image_path}: {str(e)}")
                    logger.error(f"异常详情: {traceback.format_exc()}")
                    continue
                    
            except Exception as e:
                logger.error(f"处理相似图片失败: {str(e)}")
                continue
                
        return processed_results